package com.bifrost.service.impl;

import com.bifrost.common.base.ServerResponse;
import com.bifrost.entity.MerchantStore;
import com.bifrost.entity.Role;
import com.bifrost.entity.User;
import com.bifrost.model.param.UserParam;
import com.bifrost.model.vo.MerchantStoreVO;
import com.bifrost.model.vo.PageVO;
import com.bifrost.model.vo.UserEditVO;
import com.bifrost.repository.AdminUserRepository;
import com.bifrost.repository.MerchantStoreRepository;
import com.bifrost.repository.RoleRepository;
import com.bifrost.service.AdminUserService;
import com.bifrost.util.DateUtils;
import com.bifrost.util.NumberUtils;
import com.bifrost.util.SHA256Util;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Author by yanxiaobo
 * Date on 2018/4/10$.
 */
@Service("adminUserService")
public class AdminUserServiceImpl implements AdminUserService {
    Logger log = LoggerFactory.getLogger(AdminUserServiceImpl.class);
    @Autowired
    AdminUserRepository adminUserRepository;
    @Autowired
    RoleRepository roleRepository;
    @Autowired
    MerchantStoreRepository merchantStoreRepository;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse add(UserParam userParam, Integer[] roleIds , Long[] merchantStoreIds) {
        //sha256加密
        String password = SHA256Util.SHA256EncodeToBase64(userParam.getAdminPassword());
        User user = User.builder()
                .active(userParam.isActive())
                .adminName(userParam.getAdminName())
                .adminPhone(userParam.getAdminPhone())
                .description(userParam.getDescription())
                .build();
        user.setAdminPassword(password);
        user.setCreatedTimestamp(new Date());
        String confirm_code = getConfirmCode();
        user.setConfirmCode(confirm_code);
        ServerResponse response = checkUserNameExist(user, false);
        if (!response.isSuccess())//如果用户名重复，直接返回
            return ServerResponse.createByErrorMsg(response.getMsg());
        if(ArrayUtils.isNotEmpty(roleIds)) {//如果有角色，设置角色属性
            response = checkValid(roleIds);
            if (!response.isSuccess())
                return ServerResponse.createByErrorMsg(response.getMsg());
            user.setRoles(new HashSet<>((List) response.getData()));
        }
        response = checkMerchantStore(merchantStoreIds);
        if(!response.isSuccess()){
            return ServerResponse.createByErrorMsg(response.getMsg());
        }
        List<MerchantStore> merchantStoreList = (List<MerchantStore>) response.getData();
        user.setMerchantStore(merchantStoreList.get(0));
        user.setMerchantStores(new HashSet<>(merchantStoreList));
        User retrive = adminUserRepository.save(user);
        if(null == retrive)
            return ServerResponse.createByErrorMsg("添加用户失败");
        return ServerResponse.createBySuccessMsg("添加用户成功");
    }

    /**
     * 获取核销码
     * @return
     */
    public synchronized String getConfirmCode() {
        boolean isExist = true;
        String confirm_code = "";
        while (isExist){
            confirm_code = NumberUtils.getRandomNumber(6);
            User existUser = adminUserRepository.findFirstByConfirmCode(confirm_code);
            if(existUser == null){
                isExist = false;
            }
        }
        return confirm_code;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse batchDelete(Integer[] userIds) {
        if (null == userIds)
            return ServerResponse.createByErrorMsg("参数错误");
        int[] ids = new int[userIds.length];
        int index = -1;
        for (int id : userIds)
            ids[++index] = id;
        //校验用户是否存在
        ServerResponse serverResponse = checkValid(ids);
        if (!serverResponse.isSuccess())
            return serverResponse;
        List<User> userList = (List<User>) serverResponse.getData();
        adminUserRepository.delete(userList);
        return ServerResponse.createBySuccessMsg("删除角色成功");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServerResponse update(UserParam userParam, Integer[] roleIds, Long[] merchantStoreIds, User currentUser) {
        //sha256加密
        //修改用户信息时不可修改密码 mod by wqhe
//        String password = SHA256Util.SHA256EncodeToBase64(userParam.getAdminPassword());
        User oldUser = adminUserRepository.findOne(userParam.getId());
        if(oldUser == null){
            return ServerResponse.createByErrorMsg("用户不存在");
        }
        User user = User.builder()
                .id(userParam.getId())
                .description(userParam.getDescription())
                .adminPhone(userParam.getAdminPhone())
                .adminName(userParam.getAdminName())
                .active(userParam.isActive())
                .build();
        //mod by wqhe
//        user.setAdminPassword(password);
        user.setConfirmCode(oldUser.getConfirmCode());
        user.setAdminPassword(oldUser.getAdminPassword());
        user.setUpdatedBy(currentUser.getAdminName());
        user.setUpdatedTimestamp(new Date());

        ServerResponse response = checkUserNameExist(user, true);//校验用户名是否重复
        if (!response.isSuccess())//如果用户名重复，直接返回
            return response;
        //校验用户是否存在
        ServerResponse responseForUserCheck = checkValid(user.getId().intValue());
        if (!responseForUserCheck.isSuccess())
            return responseForUserCheck;
        if(ArrayUtils.isNotEmpty(roleIds)) {
            //校验角色是否存在
            ServerResponse responseForRoleCheck = checkValid(roleIds);
            if (!responseForRoleCheck.isSuccess())
                return responseForRoleCheck;
            List<Role> roleList = (List<Role>) responseForRoleCheck.getData();
            //设置roles属性
            user.setRoles(new HashSet<>(roleList));
        }
        response = checkMerchantStore(merchantStoreIds);
        if(!response.isSuccess()){
            return ServerResponse.createByErrorMsg("未找到相关门店信息");
        }
        List<MerchantStore> merchantStoreList = (List<MerchantStore>) response.getData();
        user.setMerchantStore(merchantStoreList.get(0));
        user.setMerchantStores(new LinkedHashSet<>(merchantStoreList));
        User retrive = adminUserRepository.save(user);
        if(null == retrive) {
            return ServerResponse.createByErrorMsg("更新用户信息失败");
        }
        return ServerResponse.createBySuccessMsg("更新用户信息成功");
    }


    @Override
    public ServerResponse list(Integer currentPage, Integer pageSize, String username, String storeCode) {

        PageRequest pageRequest = new PageRequest(currentPage - 1, pageSize);//分页查询，前端页面开始为1，查询时开始为0
        Specification<User> specification = new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                ArrayList<Predicate> predicates = Lists.newArrayList();
                if (StringUtils.isNotBlank(storeCode)) {
                    SetJoin<User, MerchantStore> merchantStores = root.joinSet("merchantStores", JoinType.INNER);
                    predicates.add(cb.equal(merchantStores.get("storeCode"), storeCode));
                }
                if (StringUtils.isNotBlank(username)) {
                    predicates.add(cb.like(root.get("adminName"), username));
                }

                return cb.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };

/*
        if (null == currentPage || null == pageSize)
            return ServerResponse.createByErrorMsg("参数错误");
        if (null != username)
            return select(currentPage, pageSize, username);
        int recordCount = new Long(adminUserRepository.count()).intValue();
        if (0 == recordCount)
            return ServerResponse.createBySuccessMsg("没有用户数据");
        PageRequest pageRequest = new PageRequest(currentPage - 1, pageSize);//分页查询，前端页面开始为1，查询时开始为0*/
        Page<User> page = adminUserRepository.findAll(specification,pageRequest);
        int recordCount = (int)page.getTotalElements();
        if (null == page || CollectionUtils.isEmpty(page.getContent()))
            return ServerResponse.createBySuccessMsg("没有查询到对应的用户数据");
        List<UserEditVO> userEditVOS = new ArrayList<>();
        page.getContent().forEach(user -> {
            UserEditVO userEditVO = new UserEditVO();
            BeanUtils.copyProperties(user,userEditVO);
            userEditVO.setCreateTime(DateUtils.format(user.getCreatedTimestamp(), DateUtils.DEFAULT_DATE_FORMAT));
            Set<MerchantStoreVO> merchantStoreVOS = new HashSet<>();
            Set<MerchantStore> merchantStores = user.getMerchantStores();
            merchantStores.forEach(merchantStore -> {
                MerchantStoreVO merchantStoreVO = new MerchantStoreVO();
                BeanUtils.copyProperties(merchantStore,merchantStoreVO);
                merchantStoreVOS.add(merchantStoreVO);
            });
            userEditVO.setStoreName(CollectionUtils.isEmpty(merchantStoreVOS)?"":merchantStoreVOS.toArray(new MerchantStoreVO[merchantStoreVOS.size()])[0].getStoreName());
            userEditVO.setMerchantStoreVOS(merchantStoreVOS);
            userEditVOS.add(userEditVO);
        });
        PageVO vo = new PageVO(currentPage, pageSize, recordCount, userEditVOS);
        return ServerResponse.createBySuccess(vo);
    }

    @Override
    public ServerResponse getDetail(Integer userId) {
        if (null == userId)
            return ServerResponse.createByErrorMsg("参数错误");
        User user = adminUserRepository.findOne(userId.longValue());
        if (null == user)
            return ServerResponse.createByErrorMsg("该用户不存在");
        UserEditVO userEditVO = new UserEditVO();
        BeanUtils.copyProperties(user,userEditVO);
        List<Role> roleList = roleRepository.findAll();
        Set<MerchantStore> merchantStores = user.getMerchantStores();
        Set<MerchantStoreVO> merchantStoreVOS = new HashSet<>();
        merchantStores.forEach(merchantStore -> {
            MerchantStoreVO merchantStoreVO = new MerchantStoreVO();
            BeanUtils.copyProperties(merchantStore,merchantStoreVO);
            merchantStoreVOS.add(merchantStoreVO);
        });
        userEditVO.setMerchantStoreVOS(merchantStoreVOS);
        Map<String, Object> map = new HashMap<>();
        map.put("userEditVO", userEditVO);
        map.put("roles", roleList);
        return ServerResponse.createBySuccess(map);
    }

    @Override
    public ServerResponse select(Integer currentPage, Integer pageSize, String userName) {
        if (null == userName)
            return ServerResponse.createBySuccess();
        //创建查询条件数据对象
        User user = new User();
        user.setAdminName(userName);
        user.setCreatedTimestamp(null);
        //创建匹配器，即如何使用查询条件
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);//模糊查询% + str + %
        //创建实例
        Example<User> ex = Example.of(user, matcher);
        Long recordCount = adminUserRepository.count(ex);

        PageRequest pageRequest = new PageRequest(currentPage - 1, pageSize);//分页查询，前端页面开始为1，查询时开始为0
        //查询
        Page<User> page = adminUserRepository.findAll(ex, pageRequest);
        if (null == page || CollectionUtils.isEmpty(page.getContent()))
            return ServerResponse.createBySuccessMsg("没有查询到对应的用户数据");
        PageVO vo = new PageVO(currentPage, pageSize, recordCount.intValue(), page.getContent());
        return ServerResponse.createBySuccess(vo);
    }

    /**
     * 管理用户密码修改
     * @param adminName
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updatePassword(String adminName, String oldPassword, String newPassword, User currentUser) {
        //校验原密码是否正确
        oldPassword = SHA256Util.SHA256EncodeToBase64(oldPassword);
        newPassword = SHA256Util.SHA256EncodeToBase64(newPassword);
        User user = adminUserRepository.findByAdminNameAndAdminPassword(adminName,oldPassword);
        user.setAdminPassword(newPassword);
        user.setUpdatedBy(currentUser.getAdminName());
        user.setUpdatedTimestamp(new Date());
        user = adminUserRepository.save(user);
        if(user == null){
            return "saveError";
        }
        return "ok";
    }

    /**
     * 管理员密码重置
     * @param adminId
     * @param defaultPassword
     *@param currentUser  @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String resetPassword(Long adminId, String defaultPassword, User currentUser) {
        User user = adminUserRepository.findOne(adminId);
        if(user == null){
            return "adminIdError";
        }
        user.setUpdatedTimestamp(new Date());
        user.setUpdatedBy(currentUser.getAdminName());
        //加密后设置初始密码
        user.setAdminPassword(SHA256Util.SHA256EncodeToBase64(defaultPassword));
        User saveUser = adminUserRepository.save(user);
        if(saveUser == null){
            return "resetError";
        }
        return "ok";
    }




    //===========================================================

    /**
     * 校验用户是否存在
     *
     * @param userId 要校验的用户的id
     * @return
     */
    public ServerResponse checkValid(Integer userId) {
        if (null == userId)
            return ServerResponse.createByErrorMsg("参数错误");
        User user = adminUserRepository.findOne(userId.longValue());
        return null == user ? ServerResponse.createByErrorMsg("不存在该用户") : ServerResponse.createBySuccess(user);
    }


    public ServerResponse checkValid(int[] userIds) {
        if (ArrayUtils.isEmpty(userIds))
            return ServerResponse.createByErrorMsg("参数错误");
        List<Long> idList = new ArrayList<>(userIds.length);
        for (Integer id : userIds)
            idList.add(id.longValue());
        List<User> userList = adminUserRepository.findAll(idList);
        if (CollectionUtils.isEmpty(userList) || userList.size() != userIds.length)
            return ServerResponse.createByErrorMsg("角色无效");
        return ServerResponse.createBySuccess(userList);

    }

    /**
     * 校验角色是否有效
     *
     * @param roleIds 需要校验的角色的id
     * @return
     */
    public ServerResponse checkValid(Integer[] roleIds) {
        if (ArrayUtils.isEmpty(roleIds))
            return ServerResponse.createByErrorMsg("参数错误，角色id不能为空");
        List<Integer> idList = new ArrayList<>(roleIds.length);
        for (Integer id : roleIds)
            idList.add(id);
        List<Role> roleList = roleRepository.findAll(idList);
        if (CollectionUtils.isEmpty(roleList) || roleList.size() != roleIds.length)
            return ServerResponse.createByErrorMsg("角色无效");
        return ServerResponse.createBySuccess(roleList);
    }

    /**
     * 使用用户名校验用户是否存在
     *
     * @param user
     * @param isUpdateOperation 表示校验用户存在是针对增加还是更新 true为更新
     * @return 如果存在，ServerResponse返回error message=“用户名已经被使用"
     */
    public ServerResponse checkUserNameExist(User user, boolean isUpdateOperation) {
        if (null == user || StringUtils.isEmpty(user.getAdminName()))
            return ServerResponse.createByErrorMsg("请确认用户名是否填写");
        User user1 = adminUserRepository.findFirstByAdminName(user.getAdminName());
        if (null == user1)//如果查询出来为空，那么该用户名一定没有重复
            return ServerResponse.createBySuccess();
        if (isUpdateOperation) {//如果是更新操作
            if (user.getId() .equals( user1.getId())) {//如果查询出来的持有该用户名的是他自己，则证明用户名没有更改
                return ServerResponse.createBySuccess();
            }
        }
        return ServerResponse.createByErrorMsg("用户名已经被使用");
    }

    public ServerResponse checkMerchantStore(Long merchantStoreIds[]){
        List<MerchantStore> merchantStoreList = new ArrayList<>();
        if(ArrayUtils.isNotEmpty(merchantStoreIds)){//如果有门店，则设置选择的门店
            for(Long merchantStoreId : merchantStoreIds){
                MerchantStore merchantStore = merchantStoreRepository.findOne(merchantStoreId);
                if(merchantStore == null){
                    return ServerResponse.createBySuccess("未找到相关门店信息");
                }
                merchantStoreList.add(merchantStore);
            }
        }else {
            merchantStoreList = merchantStoreRepository.findAll();
        }
        return ServerResponse.createBySuccess(merchantStoreList);
    }


    @Override
    public List<User> findUserByMerchantId(Long merchantId) {

        List<User> users=adminUserRepository.findUserByMerchantId(merchantId);
        return users;
    }

    @Override
    public User findUserByCode(String code) {

        return adminUserRepository.findFirstByConfirmCode(code);
    }

    @Override
    public User findById(Long userId) {
        return userId==null?null:adminUserRepository.findOne(userId);
    }

}
